﻿using GameToolkit.BehaviourTree;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GameToolkit
{
    [System.Serializable]
    [JsonImporter(FormerlySerializedAs = "StoryGraphAsset")]
    public sealed class TaskGraphAsset : ScriptableObject, IThreadSafeTitle
    {
        [System.Serializable]
        public abstract class NodeAsset
        {
#if UNITY_EDITOR
            [SerializeField, HideInInspector]
            internal Vector2 m_Position;

            [SerializeField, HideInInspector]
            internal bool m_Expend = true;

#endif
            [SerializeField, HideInInspector]
#if UNITY_EDITOR
            internal
#endif
            string _guid;
            public string guid => _guid;
        }

#if UNITY_EDITOR

        [SerializeField, HideInInspector]
        internal Vector2 m_StartPosition;

#endif

//        [SerializeField, HideInInspector]
//#if UNITY_EDITOR
//        internal
//#endif
//        string _guid;
//        public string guid => _guid;

        [SerializeField, HideInInspector]
#if UNITY_EDITOR
        internal
#endif
        int m_StartNode;

        [SerializeField, HideInInspector]
#if UNITY_EDITOR
        internal
#endif
            int m_ActiveBufferSize;

        [SerializeField, HideInInspector]
#if UNITY_EDITOR
        internal
#endif
        int m_TaskCount;

        [SerializeReference, HideInInspector]
#if UNITY_EDITOR
        internal
#endif
        NodeAsset[] m_Nodes;

        internal int TaskCount => m_TaskCount;
        internal int ActiveBufferSize => m_ActiveBufferSize;
        public int NodesCount => m_Nodes == null ? 0 : m_Nodes.Length;
        public NodeAsset this[int index] => m_Nodes[index];
        public NodeAsset StartNode => m_Nodes != null && m_StartNode >= 0 && m_StartNode < m_Nodes.Length ? m_Nodes[m_StartNode] : null;

        string mCachedName;
        public string Title => mCachedName;

        private void Awake()
        {
            mCachedName = name;
        }

        public void ResetTitle()
        {
            mCachedName = name;
        }

#if UNITY_EDITOR

        public static System.Action<TaskGraph> OpenGraph { get; internal set; }
        public static System.Action<TaskGraphAsset> OpenAsset { get; internal set; }

        HashSet<TaskGraph> mRuntimeGraphs = new HashSet<TaskGraph>();

        internal TaskGraph GetFirstGraph()
        {
            lock (mRuntimeGraphs)
            {
                return mRuntimeGraphs.Count > 0 ? mRuntimeGraphs.First() : null;
            }
        }

        internal void GetActiveGraphs(ICollection<TaskGraph> graphs)
        {
            lock (mRuntimeGraphs)
            {
                foreach(var graph in mRuntimeGraphs)
                {
                    graphs.Add(graph);
                }
            }
        }

        internal void AddGraph(TaskGraph graph)
        {
            lock (mRuntimeGraphs)
            {
                mRuntimeGraphs.Add(graph);
            }
        }

        internal void RemoveGraph(TaskGraph graph)
        {
            lock (mRuntimeGraphs)
            {
                mRuntimeGraphs.Remove(graph);
            }
        }

        //[ContextMenu("Debug First Graph", true)]
        //bool CanDebug()
        //{
        //    return mRuntimeGraphs.Count > 0 && OpenGraph != null;
        //}

        //[ContextMenu("Debug First Graph")]
        //void DebugGraph()
        //{
        //    if(mRuntimeGraphs.Count > 0)
        //    {
        //        var graph = mRuntimeGraphs.First();
        //        OpenGraph(graph);
        //    }
        //}

        private void OnValidate()
        {
            mCachedName = name;
        }
#endif
    }
}
